/*
 PreferenceController.m
 iSpeLL
 
 Created by liulei on 5/24/10.
 Copyright 2010 cool8jay@qq.com. All rights reserved.
 */

#import "PreferenceController.h"
#import "ISpeLLController.h"
#import "PTHotKey.h"
#import "PTHotKeyCenter.h"

@interface PreferenceController (PrivateAPI)

- (void)setupToolbar;
- (void)resizeWindowForContentView:(NSView *)view;

@end

@implementation PreferenceController

@synthesize mainRecorder;

+ (BOOL)isRunAtLogin {
	int ret = [UKLoginItemRegistry indexForLoginItemWithPath:[[NSBundle mainBundle] bundlePath]];
	return (ret >= 0);
}

- (void)windowDidLoad{
	[preferencesWindow setTitle:@"General"];
	[showTipCheckbox setState:[self isShowTip]];
	[alwaysOnTopCheckbox setState:[self isAlwaysOnTop]];
	[showDockIconCheckBox setState:[self isShowDockIcon]];
	[runAtLogonCheckBox setState:[PreferenceController isRunAtLogin]];
	
	KeyCombo myKeyCombo= SRMakeKeyCombo([[[[NSUserDefaults standardUserDefaults] dictionaryForKey:C8JShowMainWindowShortcutKey] objectForKey:@"keyCode"] intValue],
										[[[[NSUserDefaults standardUserDefaults] dictionaryForKey:C8JShowMainWindowShortcutKey] objectForKey:@"modifierFlags"] intValue]);
	
	[mainRecorder setKeyCombo:myKeyCombo];
	
	mainHotKey = [[PTHotKey alloc] initWithIdentifier:@"mainHotKey"
											 keyCombo:[PTKeyCombo keyComboWithKeyCode:[mainRecorder keyCombo].code
																			modifiers:[mainRecorder cocoaToCarbonFlags:[mainRecorder keyCombo].flags]]];
	
	[self setupToolbar];
	[NSApp activateIgnoringOtherApps:FALSE];
	[[self window] makeKeyAndOrderFront:nil];
}

- (IBAction)changeRunAtLogin:(id)sender {
	if ([PreferenceController isRunAtLogin]) {
		[UKLoginItemRegistry removeLoginItemWithPath:[[NSBundle mainBundle] bundlePath]];
	} else {
		[UKLoginItemRegistry addLoginItemWithPath:[[NSBundle mainBundle] bundlePath] hideIt: NO];
	}
}

- (id)initWithSpellController:(ISpeLLController *)controller{
	if (![super initWithWindowNibName:@"Preferences"]){	
		return nil;
	}
	if(!controller){
		return nil;
	}
	iSpeLLController=controller;
	
	return self;
}


- (IBAction)changeShowTip:(id)sender{
		//NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
		//[defaults setBool:[showTipCheckbox state] forKey:C8JShowTipKey];
}

- (BOOL)isShowTip{
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	return [defaults boolForKey:C8JShowTipKey];	
}

- (IBAction)changeAlwaysOnTop:(id)sender{
	if([self isAlwaysOnTop])
	{
		[[iSpeLLController mainContentWindow] setLevel:NSFloatingWindowLevel];
		[[iSpeLLController toggleAlwaysOnTopMenuItem]setTitle:[NSString stringWithFormat:@"%C Always on top",0x2713]];
		[[iSpeLLController pinButton] setState:NSContentsCellMask];
	}else {
		[[iSpeLLController mainContentWindow]setLevel:NSNormalWindowLevel];
		[[iSpeLLController toggleAlwaysOnTopMenuItem]setTitle:[NSString stringWithFormat:@"Always on top"]];
		[[iSpeLLController pinButton] setState:NSNoCellMask];
	}
}

- (BOOL)isAlwaysOnTop{
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	return [defaults boolForKey:C8JAlwaysOnTopKey];	
}

- (IBAction)changeShowDockIcon:(id)sender{
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	
	NSString *title=@"Restart required";
	NSString *message=@"iSpeLL needs to restart itself for the new setting to take effect. Click Restart Now to do this right now or Later to keep iSpeLL running.";
	NSString *later=@"Later";
	NSString *restartNow=@"Restart Now";
	
		//Should save the change to disk immediately, can not wait for the automatic synchronization because it is about to restart! 
	[defaults synchronize];
	switch (NSRunAlertPanel(title, message, restartNow, nil, later)) {
		case NSAlertDefaultReturn:
			[self restartISpeLL];
			break;
		default:
			break;
	}
}
- (BOOL)isShowDockIcon{
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	return [defaults boolForKey:C8JShowDockIconKey];
}

/*
 Restart application.
 See here: http://vgable.com/blog/2008/10/05/restarting-your-cocoa-application/
 */
-(void)restartISpeLL{
		//$N = argv[N]
	NSString *killArg1AndOpenArg2Script = @"kill -9 $1 \n open \"$2\"";
	
		//NSTask needs its arguments to be strings
	NSString *ourPID = [NSString stringWithFormat:@"%d",
						[[NSProcessInfo processInfo] processIdentifier]];
	
		//this will be the path to the .app bundle,
		//not the executable inside it; exactly what `open` wants
	NSString * pathToUs = [[NSBundle mainBundle] bundlePath];
	
	NSArray *shArgs = [NSArray arrayWithObjects:@"-c", // -c tells sh to execute the next argument, passing it the remaining arguments.
					   killArg1AndOpenArg2Script,
					   @"", //$0 path to script (ignored)
					   ourPID, //$1 in restartScript
					   pathToUs, //$2 in the restartScript
					   nil];
	
	NSTask *restartTask = [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:shArgs];
	[restartTask waitUntilExit]; //wait for killArg1AndOpenArg2Script to finish
	
	NSLog(@"*** ERROR: %@ should have been terminated, but we are still running", pathToUs);
	assert(!"We should not be running!");
}

- (void)setupToolbar
{
	toolbar = [[[NSToolbar alloc] initWithIdentifier:@"Preference Toolbar"] autorelease];
	
		// General preferences
	toolbarItemGeneral = [[NSToolbarItem alloc] initWithItemIdentifier:PreferenceToolbarGeneral];
	
	[toolbarItemGeneral setLabel:@"General"];
	[toolbarItemGeneral setImage:[NSImage imageNamed:@"General"]];
	[toolbarItemGeneral setTarget:self];
	[toolbarItemGeneral setAction:@selector(displayPreferenceGeneral:)];
	
		// Appearance preferences
	toolbarItemAppearance = [[NSToolbarItem alloc] initWithItemIdentifier:PreferenceToolbarAppearance];
	
	[toolbarItemAppearance setLabel:@"Appearance"];
	[toolbarItemAppearance setImage:[NSImage imageNamed:@"Appearance"]];
	[toolbarItemAppearance setTarget:self];
	[toolbarItemAppearance setAction:@selector(displayPreferenceAppearance:)];
	
		// Hotkey preferences
	toolbarItemHotkey = [[NSToolbarItem alloc] initWithItemIdentifier:PreferenceToolbarHotkey];
	
	[toolbarItemHotkey setLabel:NSLocalizedString(@"Hotkey", @"")];
	[toolbarItemHotkey setImage:[NSImage imageNamed:@"Hotkey"]];
	[toolbarItemHotkey setTarget:self];
	[toolbarItemHotkey setAction:@selector(displayPreferenceHotkey:)];
	
		// Update preferences
	toolbarItemUpdate = [[NSToolbarItem alloc] initWithItemIdentifier:PreferenceToolbarUpdate];
	
	[toolbarItemUpdate setLabel:NSLocalizedString(@"Update", @"")];
	[toolbarItemUpdate setImage:[NSImage imageNamed:@"Update"]];
	[toolbarItemUpdate setTarget:self];
	[toolbarItemUpdate setAction:@selector(displayPreferenceUpdate:)];
	
	[toolbar setDelegate:self];
	[toolbar setSelectedItemIdentifier:PreferenceToolbarGeneral];
	[toolbar setAllowsUserCustomization:NO];
	
	[preferencesWindow setToolbar:toolbar];
	[preferencesWindow setShowsToolbarButton:NO];
	
	[self displayPreferenceGeneral:nil];
}

- (IBAction)displayPreferenceGeneral:(id)sender{
	[preferencesWindow setTitle:@"General"];
	[[self window] setMinSize:NSMakeSize(0, 0)];
	[[self window] setShowsResizeIndicator:NO];
	
	[toolbar setSelectedItemIdentifier:PreferenceToolbarGeneral];
	[self resizeWindowForContentView:preferenceViewGeneral];
}

- (IBAction)displayPreferenceAppearance:(id)sender{
	[preferencesWindow setTitle:@"Appearance"];
	[[self window] setMinSize:NSMakeSize(0, 0)];
	[[self window] setShowsResizeIndicator:NO];
	
	[toolbar setSelectedItemIdentifier:PreferenceToolbarAppearance];
	[self resizeWindowForContentView:preferenceViewAppearance];	
}

- (IBAction)displayPreferenceHotkey:(id)sender{
	[preferencesWindow setTitle:@"Hotkey"];
	[[self window] setMinSize:NSMakeSize(0, 0)];
	[[self window] setShowsResizeIndicator:NO];
	
	[toolbar setSelectedItemIdentifier:PreferenceToolbarHotkey];
	[self resizeWindowForContentView:preferenceViewHotkey];	
}

- (IBAction)displayPreferenceUpdate:(id)sender{
	[preferencesWindow setTitle:@"Update"];
	[[self window] setMinSize:NSMakeSize(0, 0)];
	[[self window] setShowsResizeIndicator:NO];
	
	[toolbar setSelectedItemIdentifier:PreferenceToolbarUpdate];
	[self resizeWindowForContentView:preferenceViewUpdate];	
}

/*
 resizeWindowForContentView:
 
 Resizes the window to the size of the supplied view.
 */
- (void)resizeWindowForContentView:(NSView *)view
{
		// remove all current views
	NSEnumerator *en = [[[preferencesWindow contentView] subviews] objectEnumerator];
	NSView *subview;
	
	while (subview = [en nextObject]) 
	{
		[subview removeFromSuperview];
	}
	
		// resize window
	[preferencesWindow resizeForContentView:view titleBarVisible:YES];
	
		// add view
	[[preferencesWindow contentView] addSubview:view];
	[view setFrameOrigin:NSMakePoint(0, 0)];
}

#pragma mark -
#pragma mark Shortcut recorder delegate methods
- (void)shortcutRecorder:(SRRecorderControl *)aRecorder keyComboDidChange:(KeyCombo)newKeyCombo
{
	unsigned int newFlags=newKeyCombo.flags;
	signed short newCode =newKeyCombo.code;
	
	unsigned int defaultFlags=[[[[NSUserDefaults standardUserDefaults] dictionaryForKey:C8JShowMainWindowShortcutKey] objectForKey:@"modifierFlags"] intValue];
	signed short defaultCode =	[[[[NSUserDefaults standardUserDefaults] dictionaryForKey:C8JShowMainWindowShortcutKey] objectForKey:@"keyCode"] intValue];
	
	if(defaultFlags!=newFlags||defaultCode!=newCode){
		[self unregisterShortcutKey];
		
		unsigned int flags=[mainRecorder keyCombo].flags;
		signed short code =[mainRecorder keyCombo].code;
		
		[self registerHotkeyForShowingMainWindow:flags Code:code AtInit:FALSE];
	}
}

/*
 TODO: maybe for future use, check conflicts of more than one shortcuts.
 */
- (BOOL)shortcutRecorder:(SRRecorderControl *)aRecorder isKeyCode:(signed short)keyCode andFlagsTaken:(unsigned int)flags reason:(NSString **)aReason
{
	if (aRecorder == mainRecorder)
	{
		BOOL isTaken = NO;
		/*		
		 KeyCombo kc = [delegateDisallowRecorder keyCombo];
		 
		 if (kc.code == keyCode && kc.flags == flags) isTaken = YES;
		 
		 *aReason = [delegateDisallowReasonField stringValue];
		 */		
		return isTaken;
	}
	return NO;
}

#pragma mark -
#pragma mark Shortcut actions
-(void)unregisterShortcutKey{
	if (mainHotKey != nil)
	{
		[[PTHotKeyCenter sharedCenter] unregisterHotKey:mainHotKey];
		[mainHotKey release];
		mainHotKey = nil;
	}
}

-(void)registerHotkeyForShowingMainWindow:(unsigned int)flags Code:(signed short)code AtInit:(BOOL)atInit{	
	/*
	 Register shortcut key in the hot key center
	 */
	unsigned int carbonFlags = ShortcutRecorderEmptyFlags;
	
	if (flags & NSCommandKeyMask) carbonFlags |= cmdKey;
	if (flags & NSAlternateKeyMask) carbonFlags |= optionKey;
	if (flags & NSControlKeyMask) carbonFlags |= controlKey;
	if (flags & NSShiftKeyMask) carbonFlags |= shiftKey;
	if (flags & NSFunctionKeyMask) carbonFlags |= NSFunctionKeyMask;
	
	mainHotKey = [[PTHotKey alloc] initWithIdentifier:@"mainHotKey"
											 keyCombo:[PTKeyCombo keyComboWithKeyCode:code
																			modifiers:carbonFlags]];
	
	[mainHotKey setName: @"show main window"];
	[mainHotKey setTarget: self];
	[mainHotKey setAction: @selector(toggleMainWindow:)];
	[[PTHotKeyCenter sharedCenter] registerHotKey:mainHotKey];
	
	/*
	 If this method is not called at initilization period, do not update user default for shortcut key.
	 */
	if(!atInit){
		[[NSUserDefaults standardUserDefaults] setObject:
		 [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSNumber numberWithInt:code],[NSNumber numberWithInt:flags],nil]
									 forKeys:[NSArray arrayWithObjects:@"keyCode",@"modifierFlags",nil]]
												  forKey:C8JShowMainWindowShortcutKey];		
	}
}

- (void)toggleMainWindow:(PTHotKey *)hotKey
{
	if([[iSpeLLController mainContentWindow] isVisible]){
		[[iSpeLLController mainContentWindow] close];
	}else{
		[NSApp activateIgnoringOtherApps:TRUE];
		[iSpeLLController.mainContentWindow makeKeyAndOrderFront:nil];	
	}
}

#pragma mark -
#pragma mark Toolbar delegate methods

/*
 toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
 */
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{		
	if ([itemIdentifier isEqualToString:PreferenceToolbarGeneral]) {
		return toolbarItemGeneral;
	}
	else if ([itemIdentifier isEqualToString:PreferenceToolbarAppearance]) {
		return toolbarItemAppearance;
	}
	else if ([itemIdentifier isEqualToString:PreferenceToolbarHotkey]) {
		return toolbarItemHotkey;
	}
	else if ([itemIdentifier isEqualToString:PreferenceToolbarUpdate]) {
		return toolbarItemUpdate;
	}
	return [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease];
}

/*
 toolbarAllowedItemIdentifiers:
 */
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
{
	return [NSArray arrayWithObjects:
			PreferenceToolbarGeneral,
			PreferenceToolbarAppearance,
			PreferenceToolbarHotkey,
			PreferenceToolbarUpdate,
			nil];
}

/*
 toolbarDefaultItemIdentifiers:
 */
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
{
	return [NSArray arrayWithObjects:
			PreferenceToolbarGeneral,
			PreferenceToolbarAppearance,
			PreferenceToolbarHotkey,
			PreferenceToolbarUpdate,
			nil];
}

/*
 toolbarSelectableItemIdentifiers:
 */
- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
{
	return [NSArray arrayWithObjects:
			PreferenceToolbarGeneral,
			PreferenceToolbarAppearance,
			PreferenceToolbarHotkey,
			PreferenceToolbarUpdate,
			nil];
}
@end
